<template>
  <div class="cesium-viewer-wapper">
    <div id="cesium-viewer" />
    <viewerSettingSidebar :viewerSource="viewerSource" style="top:180px" />
    <div class="tool-box-left-top">
      <!-- <p><button :class="{active}" @click="shortcutAction=!shortcutAction">启用键盘操控</button></p> -->
      <!-- <div class="slider-box-wrapper"><slider-box v-model:value="relativeHeight" :max="10000" /></div> -->
      <!-- <div class="select-box-wrapper"><a-checkbox v-model:checked="shadows">shadows</a-checkbox></div> -->
      <div class="select-box-wrapper"><select-box :options="flyOptions" /></div>
    </div>
    <div class="tool-box-left-bottom"></div>
    <GlobeRotater showTime :viewerSource="viewerSource" />
    <MousePosition show :viewerSource="viewerSource" />
  </div>
</template>

<script>
// https://sandcastle.cesium.com/?src=Camera%20Tutorial.html&label=All
import * as Cesium from '@cesiumjs';
import { defineComponent, ref, watch } from 'vue';
import { SelectBox, SliderBar } from '@components/widgets';
import { G3V } from '@g3x';
import { MousePosition, viewerSettingSidebar, GlobeRotater } from '@g3x/g3v/ui';
import {viewerMixin} from '@mixins';

const g3vOptions = {
  defaultViewRectangle: G3V.defaultViews.global.china.rectangle,
  viewers: [
    {
      dom: 'cesium-viewer',
      name: 'viewer1',
      title: 'viewer#01',
      viewer: {
        imagery: { type: 'arcgisImagery', options: { brightness: 1, show: true } },
        imageryProvider: null,
        // terrain: { type: 'default', options: { requestVertexNormals: true, requestWaterMask: true } },
        terrainProvider: null,
        shadows: false
      },
      layers: [
        // { type: 'tdtIboMap', options: { brightness: 1, show: true } },
        // { type: 'tdtImgAnno', options: { brightness: 1, show: true } },
        // { type: 'darkMask', options: { brightness: 1, alpha: 0.9 } },
        { type: 'graticule', options: { brightness: 1, show: false } }
      ],
      globe: {
        depthTestAgainstTerrain: false,
        enableLighting: true //启用以太阳为光源的地球
      },
      bottomContainer: false,
      navigation: {
        // defaultResetView: G3V.defaultViews.global.china.rectangle ,
        defaultResetView: null //flyHome
      },
      shortcutAction: false,
      hideLayers: false
      // },{
      //   dom: "cesium-viewer#2",
      //   name: "viewer2",
      //   title: "viewer 2",
      //   options:{
      //     imagery: { type: 'arcgisImagery', options: { brightness: 1, show: true } },
      //     imageryProvider: null,
      //     terrain: { type: 'default', options: { requestVertexNormals: true, requestWaterMask: true } },
      //     terrainProvider: null,
      //     shadows: false,
      //   }
    }
  ]
};

const flyOptions = {};

export default defineComponent({
  name: 'fly', // 飞行动画
  components: { SelectBox, SliderBar, viewerSettingSidebar, GlobeRotater, MousePosition },
  setup() {
    return {};
  },
  props: {},
  data() {
    return {
      g3v: null,
      flyOptions
    };
  },
  computed: {
    viewer() {
      return this.g3v && this.g3v.viewer$1;
    },
    g3vViewer() {
      return this.g3v && this.g3v.g3vViewer$1;
    },
    viewerSource() {
      const { viewer } = this;
      return { viewer };
    }
  },
  watch: {},
  mounted() {
    console.log('Camera mounted');
    this.initViewer();
  },
  beforeUnmount() {},
  unmounted() {
    this.g3v && this.g3v.destroy();
    this.g3v = null;
  },
  methods: {
    initViewer() {
      let vm = this;
      vm.g3v = new G3V(g3vOptions, () => {
        vm.onViewerInited();
        vm.initEffects();
      });
    },
    onViewerInited() {},
    initEffects() {
      const { viewer, g3vViewer } = this;
      const { scene, clock } = viewer;
      var referenceFramePrimitive;

      function flyToSanDiego() {
        viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0)
        });
      }

      function flyToHeadingPitchRoll() {
        viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(-122.22, 46.12, 5000.0),
          orientation: {
            heading: Cesium.Math.toRadians(20.0),
            pitch: Cesium.Math.toRadians(-35.0),
            roll: 0.0
          }
        });
      }

      function flyToLocation() {
        // Create callback for browser's geolocation
        function fly(position) {
          viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(position.coords.longitude, position.coords.latitude, 1000.0)
          });
        }

        // Ask browser for location, and fly there.
        navigator.geolocation.getCurrentPosition(fly);
      }

      function viewRectangle() {
        var west = -77.0;
        var south = 38.0;
        var east = -72.0;
        var north = 42.0;

        var rectangle = Cesium.Rectangle.fromDegrees(west, south, east, north);
        viewer.camera.setView({
          destination: rectangle
        });

        // Show the rectangle.  Not required; just for show.
        viewer.entities.add({
          rectangle: {
            coordinates: rectangle,
            fill: false,
            outline: true,
            outlineColor: Cesium.Color.WHITE
          }
        });
      }

      function flyToRectangle() {
        var west = -90.0;
        var south = 38.0;
        var east = -87.0;
        var north = 40.0;
        var rectangle = Cesium.Rectangle.fromDegrees(west, south, east, north);

        viewer.camera.flyTo({
          destination: rectangle
        });

        // Show the rectangle.  Not required; just for show.
        viewer.entities.add({
          rectangle: {
            coordinates: rectangle,
            fill: false,
            outline: true,
            outlineColor: Cesium.Color.WHITE
          }
        });
      }

      function setReferenceFrame() {
        var center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);
        var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);

        // View in east-north-up frame
        var camera = viewer.camera;
        camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;
        camera.lookAtTransform(transform, new Cesium.Cartesian3(-120000.0, -120000.0, 120000.0));

        // Show reference frame.  Not required.
        referenceFramePrimitive = scene.primitives.add(
          new Cesium.DebugModelMatrixPrimitive({
            modelMatrix: transform,
            length: 100000.0
          })
        );
      }

      function setHeadingPitchRoll() {
        var camera = viewer.camera;
        camera.setView({
          destination: Cesium.Cartesian3.fromDegrees(-75.5847, 40.0397, 1000.0),
          orientation: {
            heading: -Cesium.Math.PI_OVER_TWO,
            pitch: -Cesium.Math.PI_OVER_FOUR,
            roll: 0.0
          }
        });
      }

      function icrf(scene, time) {
        if (scene.mode !== Cesium.SceneMode.SCENE3D) {
          return;
        }

        var icrfToFixed = Cesium.Transforms.computeIcrfToFixedMatrix(time);
        if (Cesium.defined(icrfToFixed)) {
          var camera = viewer.camera;
          var offset = Cesium.Cartesian3.clone(camera.position);
          var transform = Cesium.Matrix4.fromRotationTranslation(icrfToFixed);
          camera.lookAtTransform(transform, offset);
        }
      }

      function viewInICRF() {
        viewer.camera.flyHome(0);

        clock.multiplier = 3 * 60 * 60;
        scene.postUpdate.addEventListener(icrf);
        scene.globe.enableLighting = true;
      }

      var viewChanged = document.getElementById('viewChanged');

      var removeStart;
      var removeEnd;

      function cameraEvents() {
        var camera = viewer.camera;
        removeStart = camera.moveStart.addEventListener(function() {
          viewChanged.style.display = 'block';
        });
        removeEnd = camera.moveEnd.addEventListener(function() {
          viewChanged.style.display = 'none';
        });
      }

      var cameraChanged = document.getElementById('cameraChanged');

      var removeChanged;

      function cameraChanges() {
        var i = 0;
        removeChanged = viewer.camera.changed.addEventListener(function(percentage) {
          ++i;
          cameraChanged.innerText = 'Camera Changed: ' + i + ', ' + percentage.toFixed(6);
          cameraChanged.style.display = 'block';
        });
      }

      function flyInACity() {
        var camera = scene.camera;
        camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(-73.98580932617188, 40.74843406689482, 363.34038727246224),
          complete: function() {
            setTimeout(function() {
              camera.flyTo({
                destination: Cesium.Cartesian3.fromDegrees(-73.98585975679403, 40.75759944127251, 186.50838555841779),
                orientation: {
                  heading: Cesium.Math.toRadians(200.0),
                  pitch: Cesium.Math.toRadians(-50.0)
                },
                easingFunction: Cesium.EasingFunction.LINEAR_NONE
              });
            }, 1000);
          }
        });
      }

      function losAngelesToTokyo(adjustPitch) {
        var camera = scene.camera;

        var tokyoOptions = {
          destination: Cesium.Cartesian3.fromDegrees(139.8148, 35.7142, 20000.0),
          orientation: {
            heading: Cesium.Math.toRadians(15.0),
            pitch: Cesium.Math.toRadians(-60),
            roll: 0.0
          },
          duration: 20,
          flyOverLongitude: Cesium.Math.toRadians(60.0)
        };

        var laOptions = {
          destination: Cesium.Cartesian3.fromDegrees(-117.729, 34.457, 10000.0),
          duration: 5,
          orientation: {
            heading: Cesium.Math.toRadians(-15.0),
            pitch: -Cesium.Math.PI_OVER_FOUR,
            roll: 0.0
          }
        };

        laOptions.complete = function() {
          setTimeout(function() {
            camera.flyTo(tokyoOptions);
          }, 1000);
        };

        if (adjustPitch) {
          tokyoOptions.pitchAdjustHeight = 1000;
          laOptions.pitchAdjustHeight = 1000;
        }

        camera.flyTo(laOptions);
      }

      function flyOverLongitude(adjustPitch) {
        losAngelesToTokyo();
      }

      function flyOverLongitudeWithPitch() {
        losAngelesToTokyo(true);
      }

      this.flyOptions = [
        {
          text: '请选择'
        },
        {
          text: 'In a city',
          onselect: function() {
            reset();
            flyInACity();
          }
        },
        {
          text: 'To San Diego',
          onselect: function() {
            reset();
            flyToSanDiego();
          }
        },
        {
          text: '洛杉矶经欧洲到东京',
          onselect: function() {
            reset();
            flyOverLongitude();
          }
        },
        {
          text: 'Look down during flight',
          onselect: function() {
            reset();
            flyOverLongitudeWithPitch();
          }
        },
        {
          text: 'View in ICRF',
          onselect: function() {
            reset();
            viewInICRF();
          }
        },
        {
          text: 'To a Rectangle',
          onselect: function() {
            reset();
            flyToRectangle();
          }
        },
        {
          // text: 'Fly to Location with heading, pitch and roll',
          text: 'To a location',
          onselect: function() {
            reset();
            flyToHeadingPitchRoll();
          }
        },
        {
          text: 'To My Location',
          onselect: function() {
            reset();
            flyToLocation();
          }
        },
        {
          text: 'View a Rectangle',
          onselect: function() {
            reset();
            viewRectangle();
          }
        },
        {
          text: '相机参考框架',
          onselect: function() {
            reset();
            setReferenceFrame();
          }
        },
        {
          text: 'Set camera with heading, pitch, and roll',
          onselect: function() {
            reset();
            setHeadingPitchRoll();
          }
        },
        // {
        //   text: 'Move events',
        //   onselect: function() {
        //     reset();
        //     cameraEvents();
        //   }
        // },
        // {
        //   text: 'Camera changed event',
        //   onselect: function() {
        //     reset();
        //     cameraChanges();
        //   }
        // },
      ];

      function reset() {
        scene.completeMorph();
        viewer.entities.removeAll();
        scene.primitives.remove(referenceFramePrimitive);
        scene.tweens.removeAll();

        if (Cesium.defined(removeStart)) {
          removeStart();
          removeEnd();

          viewChanged.style.display = 'none';

          removeStart = undefined;
          removeEnd = undefined;
        }

        if (Cesium.defined(removeChanged)) {
          removeChanged();
          removeChanged = undefined;

          cameraChanged.style.display = 'none';
        }

        viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);

        clock.multiplier = 1.0;
        scene.postUpdate.removeEventListener(icrf);
        scene.globe.enableLighting = false;
      }

      scene.morphComplete.addEventListener(function() {
        reset();
      });
    }
  }
});
</script>

<style lang="less">
.tool-box-left-top {
  display: flex;

  button {
    min-width: 5em;
    background-color: rgba(0, 0, 0, 0.75);
    border-color: rgba(0, 0, 0, 0);
    cursor: pointer;

    transition: all 500ms;

    &:hover {
      opacity: 0.75;
    }

    &.active {
      background-color: rgba(0, 20, 200, 0.75);
    }
  }
}
</style>
